"""
优先级管理服务
提供统一的优先级数据管理，支持缓存、版本控制和实时更新
"""
from datetime import datetime, timedelta, timezone
import asyncio
import hashlib
import json
from typing import Any
from motor.motor_asyncio import AsyncIOMotorDatabase
from ..core.response import ErrorTypes
from ..core.state_cache import state_cache
from ..models.state import StateResponse


class PriorityService:
    """优先级管理服务"""
    
    def __init__(self):
        self._version_cache: dict[str, str] = {}
        self._etag_cache: dict[str, str] = {}
        self._last_modified: dict[str, datetime] = {}
        self._lock: asyncio.Lock = asyncio.Lock()
    
    async def get_priority_options(
        self, 
        db: AsyncIOMotorDatabase,
        module_type: str,
        force_refresh: bool = False,
        if_none_match: str | None = None,
        if_modified_since: datetime | None = None
    ) -> tuple[list[dict[str, str | int | bool | None]], str, datetime]:
        """
        获取优先级选项
        
        Args:
            db: 数据库连接
            module_type: 模块类型
            force_refresh: 是否强制刷新缓存
            if_none_match: ETag验证
            if_modified_since: 最后修改时间验证
            
        Returns:
            (优先级选项列表, ETag, 最后修改时间)
        """
        cache_key = f"priority_options_{module_type}"
        
        async with self._lock:
            # 检查ETag和最后修改时间
            current_etag = self._etag_cache.get(cache_key)
            current_last_modified = self._last_modified.get(cache_key)
            
            if if_none_match and current_etag and if_none_match == current_etag:
                raise PriorityNotModifiedError("优先级数据未修改")
            
            if (if_modified_since and current_last_modified and 
                if_modified_since >= current_last_modified):
                raise PriorityNotModifiedError("优先级数据未修改")
            
            if not force_refresh and self._is_cache_valid(cache_key):
                cached_options = self._get_cached_options(cache_key)
                if cached_options and current_etag is not None and current_last_modified is not None:
                    return cached_options, current_etag, current_last_modified
            
            # 从数据库获取数据
            try:
                cursor = db.priorities.find({"module_type": module_type, "is_enabled": True}).sort("sort_order", 1)
                priorities = await cursor.to_list(length=None)
                
                options = [
                    {
                        "label": p["name"],
                        "value": p["code"],
                        "color": p["color"],
                        "icon": p.get("icon"),
                        "disabled": not p.get("is_enabled", True)
                    } for p in priorities
                ]
                
                new_etag = self._generate_etag(options)
                new_last_modified = datetime.now(timezone.utc)
                
                self._update_cache(cache_key, options, new_etag, new_last_modified)
                
                return options, new_etag, new_last_modified
                
            except Exception as e:
                cached_options = self._get_cached_options(cache_key)
                if cached_options and current_etag is not None and current_last_modified is not None:
                    return cached_options, current_etag, current_last_modified
                raise PriorityServiceError(f"获取优先级选项失败: {str(e)}")
    
    async def get_all_priority_options(
        self, 
        db: AsyncIOMotorDatabase,
        force_refresh: bool = False
    ) -> dict[str, list[dict[str, str | int | bool | None]]]:
        """获取所有模块的优先级选项"""
        result = {}
        
        # 从数据库动态获取所有模块类型
        try:
            module_types = await db.priorities.distinct("module_type")
        except Exception as e:
            raise PriorityServiceError(f"获取模块类型失败: {str(e)}")
        
        for module_type in module_types:
            try:
                options, _, _ = await self.get_priority_options(
                    db, module_type, force_refresh
                )
                result[module_type] = options
            except Exception as e:
                print(f"获取{module_type}优先级选项失败: {str(e)}")
                result[module_type] = []
        
        return result
    
    async def validate_priority_value(
        self, 
        db: AsyncIOMotorDatabase, 
        module_type: str, 
        priority_value: str
    ) -> dict[str, str | bool | dict[str, str | int | bool | None] | None]:
        """验证优先级值是否有效"""
        try:
            is_valid = await state_cache.validate_state_code(db, module_type, priority_value)
            
            if is_valid:
                state = await state_cache.get_state_by_code(db, module_type, priority_value)
                return {
                    "is_valid": True,
                    "state": state.model_dump() if state else None,
                    "message": "优先级值有效"
                }
            else:
                return {
                    "is_valid": False,
                    "state": None,
                    "message": "优先级值无效或已禁用"
                }
                
        except Exception as e:
            raise PriorityServiceError(f"验证优先级值失败: {str(e)}")
    
    async def get_priority_statistics(
        self, 
        db: AsyncIOMotorDatabase
    ) -> dict[str, dict[str, int | str | StateResponse | None]]:
        """获取优先级统计信息"""
        try:
            statistics = {}
            priority_modules = ["project_priority", "requirement_priority", "task_priority", "defect_priority"]
            
            for module_type in priority_modules:
                try:
                    states = await state_cache.get_module_states(db, module_type)
                    enabled_states = [state for state in states if state.is_enabled]
                    visible_states = [state for state in states if state.is_visible]
                    
                    statistics[module_type] = {
                        "total_count": len(states),
                        "enabled_count": len(enabled_states),
                        "visible_count": len(visible_states),
                        "default_state": next((state for state in states if state.is_default), None)
                    }
                except Exception as e:
                    statistics[module_type] = {
                        "error": str(e),
                        "total_count": 0,
                        "enabled_count": 0,
                        "visible_count": 0,
                        "default_state": None
                    }
            
            return statistics
            
        except Exception as e:
            raise PriorityServiceError(f"获取优先级统计失败: {str(e)}")
    
    async def refresh_cache(self, module_type: str | None = None) -> dict[str, int | list[str]]:
        """
        刷新缓存
        
        Args:
            module_type: 模块类型，如果为None则刷新所有模块
            
        Returns:
            包含刷新结果的字典，包括refreshed_modules（刷新的模块列表）和refreshed_count（刷新数量）
        """
        try:
            refreshed_modules: list[str] = []
            
            if module_type:
                # 清除指定模块的缓存
                cache_key = f"priority_options_{module_type}"
                
                # 检查缓存是否存在
                if cache_key in self._etag_cache or cache_key in self._last_modified or cache_key in self._version_cache:
                    _ = self._etag_cache.pop(cache_key, None)
                    _ = self._last_modified.pop(cache_key, None)
                    _ = self._version_cache.pop(cache_key, None)
                    refreshed_modules.append(module_type)
                
                # 同时清除状态缓存
                state_cache.invalidate_cache(module_type)
            else:
                # 清除所有缓存
                # 收集所有模块类型
                for cache_key in list(self._etag_cache.keys()):
                    if cache_key.startswith("priority_options_"):
                        module = cache_key.replace("priority_options_", "")
                        if module:
                            refreshed_modules.append(module)
                
                self._etag_cache.clear()
                self._last_modified.clear()
                self._version_cache.clear()
                state_cache.invalidate_cache()
            
            return {
                "refreshed_modules": refreshed_modules,
                "refreshed_count": len(refreshed_modules)
            }
                
        except Exception as e:
            raise PriorityServiceError(f"刷新缓存失败: {str(e)}")
    
    def _is_cache_valid(self, cache_key: str) -> bool:
        """检查缓存是否有效"""
        # 检查缓存是否存在且未过期
        return (
            cache_key in self._etag_cache and 
            cache_key in self._last_modified and 
            cache_key in self._version_cache and
            (datetime.now(timezone.utc) - self._last_modified[cache_key]) < timedelta(minutes=15)
        )
    
    def _get_cached_options(self, cache_key: str) -> list[dict[str, str | int | bool | None]] | None:
        """获取缓存的选项"""
        # 从内存缓存中获取数据
        if cache_key in self._version_cache:
            return self._version_cache.get(cache_key, [])
    
    def _generate_etag(self, data: list[dict[str, str | int | bool | None]]) -> str:
        """生成ETag"""
        data_str = json.dumps(data, sort_keys=True)
        return hashlib.md5(data_str.encode()).hexdigest()
    
    def _update_cache(
        self, 
        cache_key: str, 
        data: list[dict[str, Any]], 
        etag: str, 
        last_modified: datetime
    ):
        """更新缓存"""
        self._etag_cache[cache_key] = etag
        self._last_modified[cache_key] = last_modified
        self._version_cache[cache_key] = data
    
    async def initialize_default_priorities(self, db: AsyncIOMotorDatabase, module_type: str) -> int:
        """初始化指定模块的默认优先级"""
        from ..models.priority import ModuleType

        priority_definitions = {
            ModuleType.PROJECT: [
                {"name": "低", "code": "low", "color": "#67C23A", "sort_order": 1},
                {"name": "中", "code": "medium", "color": "#E6A23C", "sort_order": 2, "is_default": True},
                {"name": "高", "code": "high", "color": "#F56C6C", "sort_order": 3}
            ],
            ModuleType.REQUIREMENT: [
                {"name": "低", "code": "low", "color": "#67C23A", "sort_order": 1},
                {"name": "中", "code": "medium", "color": "#E6A23C", "sort_order": 2, "is_default": True},
                {"name": "高", "code": "high", "color": "#F56C6C", "sort_order": 3},
                {"name": "紧急", "code": "urgent", "color": "#F56C6C", "sort_order": 4},
                {"name": "严重", "code": "critical", "color": "#F56C6C", "sort_order": 5}
            ],
            ModuleType.TASK: [
                {"name": "最低", "code": "lowest", "color": "#909399", "sort_order": 0},
                {"name": "低", "code": "low", "color": "#67C23A", "sort_order": 1},
                {"name": "中", "code": "medium", "color": "#E6A23C", "sort_order": 2, "is_default": True},
                {"name": "高", "code": "high", "color": "#F56C6C", "sort_order": 3},
                {"name": "最高", "code": "highest", "color": "#F56C6C", "sort_order": 4}
            ],
            ModuleType.DEFECT: [
                {"name": "最低", "code": "lowest", "color": "#909399", "sort_order": 0},
                {"name": "低", "code": "low", "color": "#67C23A", "sort_order": 1},
                {"name": "中", "code": "medium", "color": "#E6A23C", "sort_order": 2, "is_default": True},
                {"name": "高", "code": "high", "color": "#F56C6C", "sort_order": 3},
                {"name": "最高", "code": "highest", "color": "#F56C6C", "sort_order": 4}
            ],
            ModuleType.TEST_CASE: [
                {"name": "最低", "code": "lowest", "color": "#C0C4CC", "sort_order": 0},
                {"name": "低", "code": "low", "color": "#909399", "sort_order": 1},
                {"name": "中等", "code": "medium", "color": "#E6A23C", "sort_order": 2, "is_default": True},
                {"name": "高", "code": "high", "color": "#F56C6C", "sort_order": 3},
                {"name": "紧急", "code": "urgent", "color": "#F56C6C", "sort_order": 4},
                {"name": "严重", "code": "critical", "color": "#F56C6C", "sort_order": 5},
                {"name": "阻塞", "code": "blocker", "color": "#F56C6C", "sort_order": 6}
            ]
        }

        # 将字符串转换为枚举值进行比较
        module_type_enum = None
        for mt in ModuleType:
            if mt.value == module_type:
                module_type_enum = mt
                break
        
        if module_type_enum is None or module_type_enum not in priority_definitions:
            raise PriorityServiceError(f"无效的模块类型: {module_type}")

        priorities_to_create = priority_definitions[module_type_enum]
        created_count = 0

        for priority in priorities_to_create:
            priority_doc = {
                "module_type": module_type,
                "name": priority["name"],
                "code": priority["code"],
                "color": priority["color"],
                "sort_order": priority["sort_order"],
                "is_default": priority.get("is_default", False),
                "is_enabled": True,
                "created_at": datetime.now(timezone.utc),
                "updated_at": datetime.now(timezone.utc)
            }
            
            await db.priorities.update_one(
                {"module_type": module_type, "code": priority["code"]},
                {"$set": priority_doc},
                upsert=True
            )
            created_count += 1
        
        await self.refresh_cache(module_type)
        return created_count

    
    async def get_cache_info(self) -> dict[str, dict[str, str | float | bool | None]]:
        """获取缓存信息"""
        cache_info: dict[str, dict[str, str | float | bool | None]] = {}
        
        for cache_key, last_modified in self._last_modified.items():
            cache_info[cache_key] = {
                "etag": self._etag_cache.get(cache_key),
                "last_modified": last_modified.isoformat(),
                "age_seconds": (datetime.now(timezone.utc) - last_modified).total_seconds(),
                "is_valid": self._is_cache_valid(cache_key)
            }
        
        return cache_info


class PriorityServiceError(Exception):
    """优先级服务错误"""
    
    def __init__(self, message: str, error_type: str = ErrorTypes.INTERNAL_ERROR):
        self.message: str = message
        self.error_type: str = error_type
        super().__init__(message)


class PriorityNotModifiedError(PriorityServiceError):
    """优先级数据未修改错误"""
    def __init__(self, message: str = "优先级数据未修改"):
        super().__init__(message, ErrorTypes.NOT_MODIFIED_ERROR)


# 全局优先级服务实例
priority_service = PriorityService()